using System;
using System.ComponentModel;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace Microsoft.VisualStudio.WebServer.UIComponents
{
	[DefaultProperty("Text"), DefaultEvent("MouseDown")]
	public sealed class TrayIcon : Component
	{
		private class TrayIconNativeWindow : NativeWindow
		{
			internal TrayIcon reference;
			private GCHandle rootRef;
			public TrayIconNativeWindow(TrayIcon trayIcon)
			{
				this.reference = trayIcon;
			}
			~TrayIconNativeWindow()
			{
				if (base.Handle != IntPtr.Zero)
				{
					Interop.PostMessage(base.Handle, 16, IntPtr.Zero, IntPtr.Zero);
				}
			}
			public void LockReference(bool locked)
			{
				if (locked)
				{
					if (!this.rootRef.IsAllocated)
					{
						this.rootRef = GCHandle.Alloc(this.reference, GCHandleType.Normal);
						return;
					}
				}
				else
				{
					if (this.rootRef.IsAllocated)
					{
						this.rootRef.Free();
					}
				}
			}
			protected override void OnThreadException(Exception e)
			{
				Application.OnThreadException(e);
			}
			protected override void WndProc(ref Message m)
			{
				if (m.Msg == 2048)
				{
					this.reference.WmTrayMessage(ref m);
					return;
				}
				if (m.Msg == TrayIcon.WM_TASKBARCREATED)
				{
					this.reference.WmTaskbarCreated(ref m);
					return;
				}
				base.DefWndProc(ref m);
			}
		}
		private static readonly object EventMouseDown = new object();
		private static readonly object EventMouseMove = new object();
		private static readonly object EventMouseUp = new object();
		private static readonly object EventClick = new object();
		private static readonly object EventDoubleClick = new object();
		private static readonly object EventShowContextMenu = new object();
		private static int WM_TASKBARCREATED = Interop.RegisterWindowMessage("TaskbarCreated");
		private static int nextId = 0;
		private Icon _icon;
		private string _text;
		private int _id;
		private bool _added;
		private Form _owner;
		private TrayIcon.TrayIconNativeWindow window;
		private bool _doubleClick;
		private bool _visible;
		private object m_lockobject = new object();
		[Category("Action")]
		public event EventHandler DoubleClick
		{
			add
			{
				base.Events.AddHandler(TrayIcon.EventDoubleClick, value);
			}
			remove
			{
				base.Events.RemoveHandler(TrayIcon.EventDoubleClick, value);
			}
		}
		[Category("Behavior")]
		public event ShowContextMenuEventHandler ShowContextMenu
		{
			add
			{
				base.Events.AddHandler(TrayIcon.EventShowContextMenu, value);
			}
			remove
			{
				base.Events.RemoveHandler(TrayIcon.EventShowContextMenu, value);
			}
		}
		[Category("Appearance"), DefaultValue(null)]
		public Icon Icon
		{
			get
			{
				return this._icon;
			}
			set
			{
				if (this._icon != value)
				{
					this._icon = value;
					this.UpdateIcon(this._visible);
				}
			}
		}
		public Form Owner
		{
			set
			{
				if (value == null)
				{
					throw new ArgumentNullException("value");
				}
				if (this._owner != null)
				{
					throw new ArgumentException("Cannot change owner form", "value");
				}
				this._owner = value;
			}
		}
		[DefaultValue(""), Category("Appearance")]
		public string Text
		{
			set
			{
				if (value == null)
				{
					value = string.Empty;
				}
				if (!value.Equals(this._text))
				{
					if (value.Length > 127)
					{
						throw new ArgumentOutOfRangeException("value", value, "Text is limited to 127 characters");
					}
					this._text = value;
					if (this._added)
					{
						this.UpdateIcon(true);
					}
				}
			}
		}
		[DefaultValue(false), Category("Behavior")]
		public bool Visible
		{
			get
			{
				return this._visible;
			}
			set
			{
				if (this._visible != value)
				{
					this.UpdateIcon(value);
					this._visible = value;
				}
			}
		}
		public TrayIcon()
		{
			this._id = ++TrayIcon.nextId;
			this._text = string.Empty;
			this.window = new TrayIcon.TrayIconNativeWindow(this);
		}
		public TrayIcon(IContainer container) : this()
		{
			container.Add(this);
		}
		protected override void Dispose(bool disposing)
		{
			if (disposing)
			{
				if (this.window != null)
				{
					this.UpdateIcon(false);
					this.window.DestroyHandle();
					this.window = null;
					this._icon = null;
					this._text = string.Empty;
				}
				this._owner = null;
			}
			else
			{
				if (this.window != null && this.window.Handle != IntPtr.Zero)
				{
					Interop.PostMessage(this.window.Handle, 16, IntPtr.Zero, IntPtr.Zero);
					this.window.ReleaseHandle();
				}
			}
			base.Dispose(disposing);
		}
		private void OnClick(EventArgs e)
		{
			EventHandler eventHandler = (EventHandler)base.Events[TrayIcon.EventClick];
			if (eventHandler != null)
			{
				eventHandler(this, e);
			}
		}
		private void OnDoubleClick(EventArgs e)
		{
			EventHandler eventHandler = (EventHandler)base.Events[TrayIcon.EventDoubleClick];
			if (eventHandler != null)
			{
				eventHandler(this, e);
			}
		}
		private void OnMouseDown(MouseEventArgs e)
		{
			MouseEventHandler mouseEventHandler = (MouseEventHandler)base.Events[TrayIcon.EventMouseDown];
			if (mouseEventHandler != null)
			{
				mouseEventHandler(this, e);
			}
		}
		private void OnMouseMove(MouseEventArgs e)
		{
			MouseEventHandler mouseEventHandler = (MouseEventHandler)base.Events[TrayIcon.EventMouseMove];
			if (mouseEventHandler != null)
			{
				mouseEventHandler(this, e);
			}
		}
		private void OnMouseUp(MouseEventArgs e)
		{
			MouseEventHandler mouseEventHandler = (MouseEventHandler)base.Events[TrayIcon.EventMouseUp];
			if (mouseEventHandler != null)
			{
				mouseEventHandler(this, e);
			}
		}
		private void OnShowContextMenu()
		{
			if (this._owner != null && this._owner.IsHandleCreated)
			{
				ShowContextMenuEventHandler showContextMenuEventHandler = (ShowContextMenuEventHandler)base.Events[TrayIcon.EventShowContextMenu];
				if (showContextMenuEventHandler != null)
				{
					Interop.POINT pOINT = default(Interop.POINT);
					Interop.GetCursorPos(ref  pOINT);
					Point point = new Point(pOINT.x, pOINT.y);
					point = this._owner.PointToClient(point);
					Interop.SetForegroundWindow(this._owner.Handle);
					ShowContextMenuEventArgs e = new ShowContextMenuEventArgs(point, false);
					showContextMenuEventHandler(this, e);
					Interop.PostMessage(this._owner.Handle, 0, IntPtr.Zero, IntPtr.Zero);
				}
			}
		}
		public void ShowBalloon(string title, string message, int seconds)
		{
			if (!this._added)
			{
				throw new ApplicationException("Must set TrayIcon to be visible before showing a balloon");
			}
			if (title == null || title.Length == 0)
			{
				throw new ArgumentNullException("title");
			}
			if (title.Length > 63)
			{
				throw new ArgumentOutOfRangeException("title", title, "Title is limited to 63 characters");
			}
			if (message == null)
			{
				message = string.Empty;
			}
			else
			{
				if (message.Length > 255)
				{
					throw new ArgumentOutOfRangeException("message", message, "Message is limited to 255 characters");
				}
			}
			if (seconds < 10 || seconds > 30)
			{
				throw new ArgumentOutOfRangeException("seconds", seconds, "Seconds must be between 10 and 30");
			}
			Interop.NOTIFYICONDATA nOTIFYICONDATA = new Interop.NOTIFYICONDATA();
			nOTIFYICONDATA.uFlags = 16;
			nOTIFYICONDATA.hWnd = this.window.Handle;
			nOTIFYICONDATA.uID = this._id;
			nOTIFYICONDATA.szTitle = title;
			nOTIFYICONDATA.szInfo = message;
			nOTIFYICONDATA.uTimeout = seconds * 1000;
			nOTIFYICONDATA.dwInfoFlags = 1;
			Interop.Shell_NotifyIcon(1, nOTIFYICONDATA);
		}
		private void UpdateIcon(bool showIconInTray)
		{
			if (base.DesignMode)
			{
				return;
			}
			if (this._owner == null)
			{
				return;
			}
			if (!this._added)
			{
				if (!showIconInTray)
				{
					return;
				}
				if (this._icon == null)
				{
					return;
				}
			}
			lock (this.m_lockobject)
			{
				this.window.LockReference(showIconInTray);
				Interop.NOTIFYICONDATA nOTIFYICONDATA = new Interop.NOTIFYICONDATA();
				nOTIFYICONDATA.uFlags = 7;
				nOTIFYICONDATA.uCallbackMessage = 2048;
				if (showIconInTray && this.window.Handle == IntPtr.Zero)
				{
					this.window.CreateHandle(new CreateParams());
				}
				nOTIFYICONDATA.hWnd = this.window.Handle;
				nOTIFYICONDATA.uID = this._id;
				nOTIFYICONDATA.hIcon = this._icon.Handle;
				nOTIFYICONDATA.szTip = this._text;
				nOTIFYICONDATA.uTimeout = 3;
				if (showIconInTray && this._icon != null)
				{
					if (!this._added)
					{
						Interop.Shell_NotifyIcon(0, nOTIFYICONDATA);
						this._added = true;
						Interop.Shell_NotifyIcon(4, nOTIFYICONDATA);
					}
					else
					{
						Interop.Shell_NotifyIcon(1, nOTIFYICONDATA);
					}
				}
				else
				{
					if (this._added)
					{
						Interop.Shell_NotifyIcon(2, nOTIFYICONDATA);
						this._added = false;
					}
				}
			}
		}
		private void WmMouseDown(ref Message m, MouseButtons button, int clicks)
		{
			if (clicks == 2)
			{
				this.OnDoubleClick(EventArgs.Empty);
				this._doubleClick = true;
			}
			this.OnMouseDown(new MouseEventArgs(button, clicks, 0, 0, 0));
		}
		private void WmMouseMove(ref Message m)
		{
			this.OnMouseMove(new MouseEventArgs(Control.MouseButtons, 0, 0, 0, 0));
		}
		private void WmMouseUp(ref Message m, MouseButtons button)
		{
			this.OnMouseUp(new MouseEventArgs(button, 0, 0, 0, 0));
			if (!this._doubleClick)
			{
				this.OnClick(EventArgs.Empty);
			}
			this._doubleClick = false;
		}
		private void WmTaskbarCreated(ref Message m)
		{
			this._added = false;
			this.UpdateIcon(this._visible);
		}
		private void WmTrayMessage(ref Message m)
		{
			switch ((int)m.LParam)
			{
				case 512:
				{
					this.WmMouseMove(ref m);
					return;
				}
				case 513:
				{
					this.WmMouseDown(ref m, MouseButtons.Left, 1);
					return;
				}
				case 514:
				{
					this.WmMouseUp(ref m, MouseButtons.Left);
					return;
				}
				case 515:
				{
					this.WmMouseDown(ref m, MouseButtons.Left, 2);
					return;
				}
				case 516:
				{
					this.WmMouseDown(ref m, MouseButtons.Right, 1);
					return;
				}
				case 517:
				{
					this.OnShowContextMenu();
					this.WmMouseUp(ref m, MouseButtons.Right);
					return;
				}
				case 518:
				{
					this.WmMouseDown(ref m, MouseButtons.Right, 2);
					return;
				}
				case 519:
				{
					this.WmMouseDown(ref m, MouseButtons.Middle, 1);
					return;
				}
				case 520:
				{
					this.WmMouseUp(ref m, MouseButtons.Middle);
					return;
				}
				case 521:
				{
					this.WmMouseDown(ref m, MouseButtons.Middle, 2);
					return;
				}
				default:
				{
					return;
				}
			}
		}
	}
}
